pipeline {
    agent any

    tools {
        maven 'maven3.9'
        jdk 'JDK1.8'
    }

    parameters {
        string(
            name: 'ImageVersion',
            description: '镜像版本',
            defaultValue: '1.0.0'
        )
        booleanParam(
            name: 'OnlyDeploy',
            defaultValue: false,
            description: '是否仅部署后端工程'
        )
        choice(name: 'CleanWorkspace', choices: ['true','false'],  description:'清空工作空间数据')
    }

    environment {
        //GIT仓库主机地址
        HOST_GIT="http://git.szjingshuo.top:3000"
        //Docker构建主机地址
        HOST_DOCKER="docker.szjingshuo.top"
        //项目部署主机地址
        HOST_DEPLOY="jsproj.szjingshuo.top"
        //容器镜像仓库地址
        HOST_DOCKER_REGISTRY="reg.szjingshuo.top"

        //构建项目组名称
        PROJECT_GROUP_NAME="nsmd"
        //项目GIT仓库名称
        PROJECT_REPO_NAME="nsmd-server"
        //项目部署环境
        PROJECT_DEPLOY_ENV="test"
        
        SSH_KEY_FOR_DEPLOY_HOST="jenkins_ssh_key"

        //源代码分支(可修改为参数)
        PULL_SOURCE_BRANCH="master"
        //源代码获取账号
        PULL_SOURCE_ACCOUNT="goes_for_jenkins"
        //Docker主机上传临时目录
        PROJECT_BUILD_WORKSPACE="/tmp/${env.PROJECT_REPO_NAME}"
        //项目构建镜像名称(推送至仓库镜像名称)
        PUSH_IMAGE_NAME="${env.PROJECT_REPO_NAME}-${env.PULL_SOURCE_BRANCH}:${params.ImageVersion}"
        //从GIT获取源码地址
        PULL_SOURCE_URL="${env.HOST_GIT}/${env.PROJECT_GROUP_NAME}/${env.PROJECT_REPO_NAME}.git"
    }

    stages {
        stage("环境初始化") {
            steps {
                script {
                    def java_version = sh(script:'java -version 2>&1 | grep version',returnStdout:true).trim()
                    echo "Java版本:${java_version}"
                    echo "工程名称:${env.PROJECT_REPO_NAME}"
                    echo "源码分支:${env.PULL_SOURCE_BRANCH}"
                    echo "镜像版本:${params.ImageVersion}"
                }
            }
        }


        stage("拉取仓库源码") {
            steps {
                echo "开始拉取源码"
                git branch:"${env.PULL_SOURCE_BRANCH}", credentialsId: "${env.PULL_SOURCE_ACCOUNT}", url:"${env.PULL_SOURCE_URL}"
                echo "代码拉取成功"
            }
        }
        
        stage("工程编译打包") {
            steps {
                sh """
                    echo "开始编译项目"
                    mvn clean package -Dmaven.test.skip
                    echo "项目编译成功"
                """
            }
        }
        
        
        stage("构建应用服务镜像"){
            steps {
                script {
                    //过滤包含有Dockerfile子模块
                    def hasDockerfileDirs = sh(
                        script: """
                            find . -type f -name Dockerfile -exec dirname {} \\; | xargs -n 1 basename
                        """, 
                        returnStdout: true).trim().readLines()    
                    
                    hasDockerfileDirs.each { directory -> 
                        def image_name="${env.HOST_DOCKER_REGISTRY}/${env.PROJECT_GROUP_NAME}/${directory}-${env.PULL_SOURCE_BRANCH}:${params.ImageVersion}"
                        def build_ctx="${env.PROJECT_BUILD_WORKSPACE}/${directory}"
                        //根据部署模块创建应用程序数据卷宿主机目录
                        sshPublisher(
                            publishers: [
                                sshPublisherDesc(
                                    configName: "${env.HOST_DEPLOY}",
                                    transfers: [
                                        //在部署主机提前创建好需要挂载的卷标数据目录
                                        sshTransfer(
                                            execTimeout: 120000,
                                            remoteDirectory: "${env.PROJECT_BUILD_WORKSPACE}",
                                            removePrefix: "",
                                            sourceFiles: "",
                                            execCommand: """
                                              [ ! -d "/data/${env.PROJECT_GROUP_NAME}/apps/${directory}/data" ] && mkdir -p "$directory"
                                              [ ! -d "/data/${env.PROJECT_GROUP_NAME}/apps/${directory}/log" ] && mkdir -p "$directory"

                                              # mkdir -p /data/${env.PROJECT_GROUP_NAME}/apps/${directory}/{data,log}
                                              echo "应用程序挂载卷标目录【/data/${env.PROJECT_GROUP_NAME}/apps/${directory}/{data,log}】创建成功"
                                            """
                                        )
                                    ],
                                    verbose: true
                                )
                            ]
                        )
                        //构建应用程序镜像
                        sshPublisher(
                            publishers: [
                                sshPublisherDesc(
                                    configName: "${env.HOST_DOCKER}",
                                    transfers: [
                                        //复制jar包至Docker主机等待镜像构建
                                        sshTransfer(
                                            execTimeout: 120000,
                                            remoteDirectory: "${env.PROJECT_BUILD_WORKSPACE}",
                                            removePrefix: "",
                                            sourceFiles: "${directory}/target/*.jar"
                                        ),
                                        //复制Dockerfile文件并构建
                                        sshTransfer(
                                            execTimeout: 120000,
                                            remoteDirectory: "${env.PROJECT_BUILD_WORKSPACE}",
                                            removePrefix: "",
                                            sourceFiles: "${directory}/Dockerfile",
                                            execCommand: """
                                                docker build -t ${image_name} ${build_ctx}
                                                docker push ${image_name}
                                                echo "镜像【${image_name}】上传仓库成功"
                                                # 清空docker主机镜像
                                                docker rmi ${image_name}
                                                # 修改docker-compose文件镜像名称
                                                echo "清除Docker主机镜像【${image_name}】缓存成功"
                                                # 删除本地缓存目录
                                            """
                                        ),
                                    ],
                                    verbose: true
                                )
                            ]
                        )
                    }
                    //清空临时缓存数据
                    sh("rm -rf /tmp/${env.PROJECT_GROUP_NAME}")
                }
            }
        }

        stage("部署中间件配置文件") {
            steps {
                script {
                    //列出全部配置文件目录
                    def middlewareConfigDirs = sh(
                        script: """
                            find ./deploy/confs -mindepth 1 -maxdepth 1 -type d -exec basename {} \\; | xargs -n 1 basename
                        """, 
                        returnStdout: true).trim().readLines()
                    //在部署宿主机创建中间件配置目录
                    middlewareConfigDirs.each { dir ->
                        sshPublisher(
                            publishers: [
                                sshPublisherDesc(
                                    configName: "${env.HOST_DEPLOY}",
                                    transfers: [
                                        sshTransfer(
                                            execTimeout: 120000,
                                            remoteDirectory: "${env.PROJECT_BUILD_WORKSPACE}/confs",
                                            removePrefix: "deploy/confs",
                                            sourceFiles: "deploy/confs/${dir}/**",
                                            execCommand: """
                                                echo "检测到目录${dir}"
                                                if [[ ! -d "/data/${env.PROJECT_GROUP_NAME}/${dir}" ]]; then
                                                    mkdir -p /data/${env.PROJECT_GROUP_NAME}/${dir}/{data,conf,log}
                                                    echo "${dir}目录创建成功"
                                                else
                                                    echo "${dir}目录已存在"
                                                fi
                                                //将配置文件移动至中间件配置目标
                                                cp ${env.PROJECT_BUILD_WORKSPACE}/confs/${dir}/* /data/${env.PROJECT_GROUP_NAME}/${dir}/conf
                                                //删除临时目录
                                                rm -rf ${env.PROJECT_BUILD_WORKSPACE}/confs/${dir}
                                            """
                                        )
                                    ],
                                    verbose: true
                                )
                            ]
                        )                    
                    }
                }
            }
        }
        
        stage("启动应用程序") {
            steps {
                script {
                    def docker_net_name="net_${env.PROJECT_GROUP_NAME}_${env.PROJECT_DEPLOY_ENV}"
                    def docker_compose_dir="/opt/${env.PROJECT_GROUP_NAME}"
                    def svc_name_middleware="${env.PROJECT_GROUP_NAME}-middleware"
                    def svc_name_backend="${env.PROJECT_GROUP_NAME}-backend"
                    sshPublisher(
                        publishers: [
                            sshPublisherDesc(
                                configName: "${env.HOST_DEPLOY}",
                                transfers: [
                                    sshTransfer(
                                        execTimeout: 120000,
                                        remoteDirectory: "${docker_compose_dir}",
                                        removePrefix: "deploy/compose",
                                        sourceFiles: "deploy/compose/**",
                                        execCommand: """
                                            # 检测容器网络是否已创建
                                            if [ "0" -eq "\$(docker network ls | grep ${docker_net_name} | wc -l)" ]; then
                                                docker network create ${docker_net_name}
                                                echo "容器网络【${docker_net_name}】创建成功"
                                            fi
                                            # 执行中间件服务启停
                                            if [[ \$(docker-compose ls -q | grep -q '${svc_name_middleware}') ]]; then
                                                docker-compose -p ${svc_name_middleware} -f ${docker_compose_dir}/middleware-service.yaml down
                                                echo "应用中间件已停止"
                                            fi
                                            docker-compose -p ${svc_name_middleware} -f ${docker_compose_dir}/middleware-service.yaml up -d
                                            echo "应用中间件已启动"
                                            # 执行后台服务启停
                                            if [[ \$(docker-compose ls -q | grep -q '${svc_name_backend}') ]]; then
                                                docker-compose -p ${svc_name_backend} -f ${docker_compose_dir}/backend-service.yaml down
                                                echo "应用服务已停止"
                                            fi
                                            docker-compose -p ${svc_name_backend} -f ${docker_compose_dir}/backend-service.yaml up -d
                                            echo "应用服务已启动"
                                            # 执行临时目录清理工作
                                            rm -rf ${env.PROJECT_BUILD_WORKSPACE}
                                            echo "应用服务器环境清理完成"
                                        """
                                    )
                                ],
                                verbose: true
                            )
                        ]
                    )
                }
            }
        }

        stage("清除构建缓存") {
            steps {
                echo "开始清除构建缓存"
                sshPublisher(
                    publishers: [
                        sshPublisherDesc(
                            configName: 'docker.szjingshuo.top',
                            transfers: [
                                sshTransfer(
                                    cleanRemote: false,
                                    excludes: '',
                                    execCommand: '''
                                        sudo rm -rf /tmp/${project_name}
                                        sudo docker image prune -f
                                    ''',
                                    execTimeout: 120000,
                                    sourceFiles: '/tmp'
                                )
                            ]
                        )
                    ]
                )
                echo "构建缓存清除完毕"

                 echo "项目构建完成"
            }
        }
    }
}

